package com.kzw.misc.utils;

import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.dom4j.Document;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

import com.kzw.core.Constants;
import com.kzw.core.bean.OnlineUser;
import com.kzw.core.util.XmlUtil;
import com.kzw.misc.web.filter.SecurityInterceptorFilter;
import com.kzw.oa.system.bean.TopModule;
import com.kzw.oa.system.model.AppRole;
import com.kzw.oa.system.model.AppUser;
import com.kzw.oa.system.model.SysConfig;
import com.kzw.oa.system.service.SysConfigService;

/**
 * 方便取得Spring容器，取得其他服务实例，必须在Spring的配置文件里进行配置
 * 如：<bean id="appUtil" class="com.palm.util.core.AppUtil"/> 也提供整个应用程序的相关配置获取方法
 *
 */
@Component
public class AppUtil implements ApplicationContextAware, InitializingBean {

	private static Log logger = LogFactory.getLog(AppUtil.class);

	/**
	 * 存放应用程序的配置,如邮件服务器等
	 */
	private static Map<String, String> configMap = new HashMap<>();

	// 存放在线用户,SessionId,OnlineUser
	private static Map<String, OnlineUser> onlineUsers = new LinkedHashMap<String, OnlineUser>();
	/**
	 * 在线用户的ID
	 */
	private static HashSet<Long> onlineUserIds = new HashSet<Long>();

	private static ApplicationContext appContext;

	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
		AppUtil.appContext = applicationContext;

	}
	
	@Override
	public void afterPropertiesSet() throws Exception {
		AppUtil.init();
	}

	/**
	 * 系统的左边导航菜单文档，当系统启动时， 由系统去解析menu-all.xml，并放置系统，供权限菜单使用
	 */
	private static Map<String, Document> orgMenus = null;
	/**
	 * 去除了Function与url
	 */
	private static Map<String, Document> itemsMenus = null;

	/**
	 * 系统的所有头部菜单配置
	 */
	private static Map<String, TopModule> allTopModels = null;
	/**
	 * 系统的所有菜单功能
	 */
	private static Document menuDocument = null;

	public static Map<String, Document> getOrgMenus() {
		return orgMenus;
	}

	public static Map<String, Document> getItemsMenus() {
		return itemsMenus;
	}

	public static Map<String, TopModule> getAllTopModels() {
		return allTopModels;
	}

	public static Document getMenuDocument() {
		return menuDocument;
	}

	/**
	 * 公共的顶部模块
	 */
	public static Map<String, TopModule> publicTopModules = null;

	public static Map<String, TopModule> getPublicTopModules() {
		return publicTopModules;
	}

	public static void setPublicTopModules(Map<String, TopModule> publicTopModules) {
		AppUtil.publicTopModules = publicTopModules;
	}

	/**
	 * 取得Bean
	 * 
	 * @param beanId
	 * @return
	 */
	public static Object getBean(String beanId) {
		return appContext.getBean(beanId);
	}

	public static <T> T getBean(Class<T> clazz) {
		return appContext.getBean(clazz);
	}

	/**
	 * 返回在线用户
	 * 
	 * @return
	 */
	public static Map<String, OnlineUser> getOnlineUsers() {
		return onlineUsers;
	}

	/**
	 * 移除在线用户
	 * 
	 * @param sessionId
	 */
	public static void removeOnlineUser(String sessionId) {
		OnlineUser user = onlineUsers.get(sessionId);
		if (user != null) {
			onlineUserIds.remove(user.getUserId());
		}
		onlineUsers.remove(sessionId);
	}

	/**
	 * 增加在线用户
	 * */
	public static void addOnlineUser(String sessionId, AppUser user) {
		if (!onlineUsers.containsKey(sessionId)) {
			OnlineUser onlineUser = new OnlineUser();
			onlineUser.setFullname(user.getFullname());
			onlineUser.setSessionId(sessionId);
			onlineUser.setUsername(user.getUsername());
			onlineUser.setUserId(user.getUserId());
			if (!user.getUserId().equals(AppUser.SUPER_USER)) {
				String path = user.getDept() == null ? "" : user.getDept().getPath();
				onlineUser.setDepPath("." + path);
			}
			Set<AppRole> roles = user.getRoles();
			StringBuffer roleIds = new StringBuffer(",");
			for (AppRole role : roles) {
				roleIds.append(role.getRoleId() + ",");
			}
			onlineUser.setRoleIds(roleIds.toString());
			onlineUser.setGender(user.getGender());
			onlineUsers.put(sessionId, onlineUser);
			onlineUserIds.add(user.getUserId());
		}
	}


	/**
	 * 重新加载安全权限匹配的数据源
	 */
	public static void reloadSecurityDataSource() {
		SecurityInterceptorFilter securityInterceptorFilter = (SecurityInterceptorFilter) AppUtil.getBean("securityInterceptorFilter");
		securityInterceptorFilter.loadDataSource();
	}

	/**
	 * 应用程序启动时调用
	 */
	public static void init() {
		// 读取来自config.properties文件的配置,并且放入configMap内,应用程序共同使用
		Properties props = new Properties();
		try {
			InputStream fis = AppUtil.class.getResourceAsStream("/conf/config.properties");
			Reader r = new InputStreamReader(fis, "UTF-8");
			props.load(r);
			Iterator<Object> it = props.keySet().iterator();
			while (it.hasNext()) {
				String key = (String) it.next();
				configMap.put(key, props.getProperty(key));
			}
		} catch (Exception ex) {
			logger.error(ex.getMessage());
		}

		// 从系统配置中读取所有的信息
		reloadSysConfig();

		// 加载菜单转换器
		reloadMenu();
	}

	/**
	 * 重新加载菜单配置
	 */
	public static void reloadMenu() {
		try {
			/********************使用License时需要*********************/
//			LicenseContent content = LicenseUtil.install();
//			if(content == null) {
//				long[] arr = new long[] {0x7DDF10CCA33A29A8L, 0xB0076263BBC81A0L, 0xD4B6FD1B3C3E2876L, 0x4D9448FFCB2E2DB7L, 0xB7B6AF8330D3DF36L};
//				ObfuscatedString msg = new ObfuscatedString(arr);
//				System.err.println(msg.toString());
//				System.exit(2);
//			}			
//			orgMenus = content.getMenus();			
			/********************不使用License时需要********************/
			orgMenus = MenuUtil.getAllOrgMenus();
			/********************   === end ===  ********************/
			
			itemsMenus = MenuUtil.getAllItemsMenus(orgMenus);
			menuDocument = MenuUtil.mergeOneDoc(orgMenus);
			allTopModels = MenuUtil.getTopModules(menuDocument);
			publicTopModules = MenuUtil.getPublicTopModules(allTopModels);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 取得用于授权的文档，即转化后，去掉url的元素
	 * 
	 * @return
	 */
	public static Document getGrantMenuDocument() {
		Document finalDoc = null;
		try {
			InputStream is = AppUtil.class.getResourceAsStream("/menu/menu-grant.xsl");
			finalDoc = XmlUtil.styleDocument(menuDocument, is);
		} catch (Exception ex) {
			logger.error("menu-grant.xsl transform has error:" + ex.getMessage());
		}
		return finalDoc;
	}

	/*
	 * 是否同步菜单
	 */
	public static boolean getIsSynMenu() {
		String synMenu = (String) configMap.get("isSynMenu");
		if ("true".equals(synMenu)) {
			return true;
		}
		return false;
	}

	/**
	 * 获取系统配置MAP
	 */
	public static Map<String, String> getSysConfig() {
		return configMap;
	}
	
	/**
	 * 获得系统配置的值
	 * */
	public static String getConfig(String prop) {
		return configMap.get(prop);
	}
	
	/**
	 * 获得系统配置的值
	 * */
	public static String getConfig(String prop, String defaultVal) {
		return StringUtils.defaultIfBlank(configMap.get(prop), defaultVal);
	}

	public static void reloadSysConfig() {
		SysConfigService sysConfigService = getBean(SysConfigService.class);
		List<SysConfig> list = sysConfigService.getAll();
		for (SysConfig conf : list) {
			configMap.put(conf.getConfigKey(), conf.getDataValue());
		}
	}

	public static String getCompanyLogo() {
		String defaultLogoPath = Constants.DEFAULT_LOGO;
		String path = (String) configMap.get(Constants.COMPANY_LOGO);
		if (StringUtils.isNotEmpty(path)) {
			defaultLogoPath = "/attachFiles/" + path;
		}
		return defaultLogoPath;
	}

	public static String getCompanyName() {
		String defaultName = Constants.DEFAULT_COMPANYNAME;
		String companyName = (String) configMap.get(Constants.COMPANY_NAME);
		if (StringUtils.isNotEmpty(companyName)) {
			defaultName = companyName;
		}
		return defaultName;
	}

	public static String getRootOrgName() {
		String defaultName = "全部";
		String orgName = (String) configMap.get("root.orgName");
		if (StringUtils.isNotEmpty(orgName)) {
			defaultName = orgName;
		}
		return defaultName;
	}

	/**
	 * 是否为安装模式
	 * 
	 * @return
	 */
	public static boolean isSetupMode() {
		String isSetupMode = (String) configMap.get("setupMode");
		if ("true".equals(isSetupMode)) {
			return true;
		}
		return false;
	}

	public static HashSet<Long> getOnlineUserIds() {
		return onlineUserIds;
	}

}
